package lovebomb.jfilesearch.engine;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.EnumSet;

import lovebomb.jfilesearch.SearchForm;
import lovebomb.jfilesearch.engine.filetype.FileRead;
import lovebomb.jfilesearch.engine.filetype.MSOfficeRead;
import lovebomb.jfilesearch.engine.filetype.PDFRead;

public class FileSearchEngine implements FileVisitor,Runnable{
	
	private final String EXT_EXCEL_NOT2007 = ".xls";
	private final String EXT_EXCEL_2007 = ".xlsx";
	private final String EXT_WORD_NOT2007 = ".doc";
	private final String EXT_WORD_2007 = ".docx";
	private final String EXT_POWERPOINT_NOT2007 = ".ppt";
	private final String EXT_POWERPOINT_2007 = ".pptx";
	private final String EXT_PDF = ".pdf";	
	
	private final String[] else_ext = new String[]{".txt",".htm",".html",".jsp",".js",".css"};
	private String index = null;
	private String path = null;
	
	private MSOfficeRead msRead = null;
	private PDFRead pdfRead = null;
	private FileRead fileRead = null;
	
	private static FileSearchEngine searchEngine = null;
	private ArrayList<String> findFiles = new ArrayList<>();
	
	private SearchForm sFrm = null;
	
	private FileSearchEngine(){
		
	}
	
	public static FileSearchEngine getInstance(){
		if( searchEngine == null){
			searchEngine = new FileSearchEngine();
		}		
		return searchEngine;
	}	
	
	public void init( SearchForm sFrm , String path, String index){
		this.sFrm = sFrm;
		this.path = path;
		this.index = index;
		
		msRead = MSOfficeRead.getInstance();
		pdfRead = PDFRead.getInstance();
		fileRead = FileRead.getInstance();
	}
	
	public void run(){
		start();
	}
	
	
	public ArrayList<String> start( ){
        EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
        Path path = FileSystems.getDefault().getPath(this.path);
        try {
        	Files.walkFileTree(path, opts, Integer.MAX_VALUE, this);	
		} catch (Exception e) {
			e.printStackTrace();
		}                
        
        return findFiles;
	}
	
	@SuppressWarnings("finally")
	public ArrayList<String> getUserFileExtList(){
		ArrayList<String> extList = new ArrayList<>();
		
		Path path = Paths.get("do_use_ext.list");
		
		Charset charset = Charset.forName("UTF-8");
        try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
            String line = null;

            while ((line = reader.readLine()) != null) {
               extList.add( line);
            }
            
        } catch (IOException e) {
        	e.printStackTrace();
        } finally {
            return extList;
        }
	}
	
	public void setUserFileExtList( ArrayList<String> extList){
		
	}
	
	private String checkFile( Path path){
		
		String fileName = path.toString().toLowerCase();
		
		for (int i = 0; i < else_ext.length; i++) {
			if( fileName.endsWith( else_ext[i]) == true){
				this.sFrm.setFileConsole( new File( fileName).getName());
				return fileName;
			}
		}		
		return null;
	}
	
	private void search( Path path){
		
		String strNote = null;	
		
		String strFile = this.checkFile(path);
		
		if( strFile != null){
				
			if( strFile.endsWith(EXT_EXCEL_2007) || strFile.endsWith(EXT_EXCEL_NOT2007)){
				strNote = msRead.readExcelFile(strFile);
			}
			else if( strFile.endsWith(EXT_POWERPOINT_2007) || strFile.endsWith(EXT_POWERPOINT_NOT2007)){
				strNote = msRead.readPowerPointFile(strFile);
			}
			else if( strFile.endsWith( EXT_WORD_2007) || strFile.endsWith( EXT_WORD_NOT2007)){
				strNote = msRead.readWordFile(strFile);
			}
			else if( strFile.endsWith( EXT_PDF)){
				strNote = pdfRead.readPDF(strFile);
			}
			else{
				for (int i = 0; i < else_ext.length; i++) {
					if( strFile.endsWith( else_ext[i]) == true){
						strNote = fileRead.readFile(strFile);
					}
				}
			}
			
			if( strNote.contains( this.index)){
				findFiles.add( strFile);
				this.sFrm.setResultColsole(strFile);
			}			
		}
	}
	
    @Override
    public FileVisitResult postVisitDirectory(Object dir, IOException exc) throws IOException {
    	
    	return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs) throws IOException {
    	this.sFrm.setFolderConsole(""+(Path) dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Object file, BasicFileAttributes attrs) throws IOException {    	
        search( (Path)file);
        
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Object file, IOException exc) throws IOException {
        return FileVisitResult.CONTINUE;
    }	
    
}
